﻿using System;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.IO;

namespace BackupRestore.BackupRestoreFramework 
{
    /// <summary>
    /// Used to specify the backup's specs, i.e.
    /// a)  the files or folders that need to be backed up
    /// b)  Total size of the backup (i.e. the sum of the sizes of all the files being backed up)
    /// c)  The total number of files being backed up
    /// </summary>
    class BackupSpecification : IEnumerable
    {
        /// <summary>
        /// To store all the paths to back up (directories or files).  
        /// </summary>
        private HashSet<FileSystemInfo> PathsToBackup = new HashSet<FileSystemInfo>();
        private static string _className;

        /// <summary>
        /// The total size of the backup in bytes
        /// </summary>
        public ulong BackupSize
        {
            get;
            set;
        }

        /// <summary>
        /// Number of files being backed up
        /// </summary>
        public ulong NumberOfFiles
        {
            get;
            set;
        }

        /// <summary>
        /// Creates an empty backup specification
        /// </summary>
        public BackupSpecification ()
        {
            _className = MethodBase.GetCurrentMethod().DeclaringType.Name;
        }

        /// <summary>
        /// Creates a backup specification with the path provided
        /// </summary>
        /// <param name="path"></param>
        public BackupSpecification (string path) : this ()
        {

            AddPath(path);
        }


        /// <summary>
        /// Adds a single path to the specification
        /// </summary>
        /// <param name="path">path to add</param>
        public void AddPath (string path)
        {
            string _methodName = MethodBase.GetCurrentMethod().Name;

            Logger.Logger.LogMethodEntry(_className, _methodName);

            if (Directory.Exists(path)) // Detect if a path is a directory.  If it is, add it as a directory.  Otherwise add as a File.
            {
                PathsToBackup.Add(new DirectoryInfo(path));
            }
            else
            {
                PathsToBackup.Add(new FileInfo(path));
            }
            Logger.Logger.LogMethodExit(_className, _methodName);
        }

        /// <summary>
        /// Adds a list of paths to the specification
        /// </summary>
        /// <param name="paths">list of paths as an array</param>
        public void AddPaths (string [] paths )
        {
            string _methodName = MethodBase.GetCurrentMethod().Name;

            Logger.Logger.LogMethodEntry(_className, _methodName);
            
            foreach (string path in paths)
            {
                AddPath (path);
            }

            Logger.Logger.LogMethodExit(_className, _methodName);
        }

        /// <summary>
        /// Gets an enumarator over the paths to back up
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            foreach (FileSystemInfo Path in PathsToBackup)
            {
                yield return Path;
            }
        }

        public override String ToString()
        {
            StringBuilder StringRep = new StringBuilder();

            foreach (FileSystemInfo Path in this)
            {
                StringRep.Append(Path.ToString() + " \r\n");
            }

            return StringRep.ToString().Trim();
        }
    }
}
